Improve VMX guest TSC accuracy when guests are
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 8 Dec 2005 14:13:38 +0000 (15:13 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 8 Dec 2005 14:13:38 +0000 (15:13 +0100)
competing for the same physical CPU.

Signed-off-by: Eddie Dong <eddie.dong@intel.com>
xen/arch/x86/vmx.c
xen/arch/x86/vmx_intercept.c
xen/arch/x86/vmx_io.c
xen/arch/x86/vmx_vmcs.c
xen/include/asm-x86/vmx_vpit.h

index b4878317a0962c081a5221aca95934cc15e3e360..e8e1c9f1e0d8fe21a77aae1544f0f53415216248 100644 (file)
@@ -108,7 +108,7 @@ void vmx_relinquish_resources(struct vcpu *v)
     destroy_vmcs(&v->arch.arch_vmx);
     free_monitor_pagetable(v);
     vpit = &v->domain->arch.vmx_platform.vmx_pit;
-    if ( vpit->ticking && active_ac_timer(&(vpit->pit_timer)) )
+    if ( active_ac_timer(&(vpit->pit_timer)) )
         rem_ac_timer(&vpit->pit_timer);
     if ( active_ac_timer(&v->arch.arch_vmx.hlt_timer) ) {
         rem_ac_timer(&v->arch.arch_vmx.hlt_timer);
index 67029c2c959d7436d837584ba8dae5b4322ff1ed..69aeb4f32591f283e4202d3f58ad69c5a2c1f592 100644 (file)
@@ -387,7 +387,6 @@ void vmx_hooks_assist(struct vcpu *v)
         }
         else {
             init_ac_timer(&vpit->pit_timer, pit_timer_fn, v, v->processor);
-            vpit->ticking = 1;
         }
 
         /* init count for this channel */
index 5557e034745a8a70ec3c7f052f90c3283686319d..5caa59bc0483c1e128d0ca557b4407addd0c3c2a 100644 (file)
@@ -793,29 +793,39 @@ static __inline__ int find_highest_irq(u32 *pintr)
     return __fls(pintr[0]);
 }
 
+void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit)
+{
+    u64   drift;
+
+    if ( vpit->first_injected )
+        drift = vpit->period_cycles * vpit->pending_intr_nr;
+    else 
+        drift = 0;
+    drift = v->arch.arch_vmx.tsc_offset - drift;
+    __vmwrite(TSC_OFFSET, drift);
+
+#if defined (__i386__)
+    __vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
+#endif
+}
+
 #define BSP_CPU(v)    (!(v->vcpu_id))
 static inline void
 interrupt_post_injection(struct vcpu * v, int vector, int type)
 {
     struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
-    u64    drift;
 
     if ( is_pit_irq(v, vector, type) ) {
         if ( !vpit->first_injected ) {
-            vpit->first_injected = 1;
             vpit->pending_intr_nr = 0;
+            vpit->scheduled = NOW() + vpit->period;
+            set_ac_timer(&vpit->pit_timer, vpit->scheduled);
+            vpit->first_injected = 1;
         } else {
             vpit->pending_intr_nr--;
         }
         vpit->inject_point = NOW();
-        drift = vpit->period_cycles * vpit->pending_intr_nr;
-        drift = v->arch.arch_vmx.tsc_offset - drift;
-        __vmwrite(TSC_OFFSET, drift);
-
-#if defined (__i386__)
-        __vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
-#endif
-
+        set_tsc_shift (v, vpit);
     }
 
     switch(type)
@@ -982,8 +992,10 @@ void vmx_do_resume(struct vcpu *v)
             vmx_wait_io();
     }
     /* pick up the elapsed PIT ticks and re-enable pit_timer */
-    if ( vpit->ticking )
+    if ( vpit->first_injected ) {
         pickup_deactive_ticks(vpit);
+    }
+    set_tsc_shift(v,vpit);
 
     /* We can't resume the guest if we're waiting on I/O */
     ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
index 04b5c6bc25e932b63092afad2cb571ac7fc50f0b..55d7741f2e39ea9df1cf3c2340d32054ad1fefbf 100644 (file)
@@ -290,6 +290,7 @@ static void vmx_do_launch(struct vcpu *v)
 /* Update CR3, GDT, LDT, TR */
     unsigned int  error = 0;
     unsigned long cr0, cr4;
+    u64     host_tsc;
 
     if (v->vcpu_id == 0)
         vmx_setup_platform(v->domain);
@@ -337,6 +338,10 @@ static void vmx_do_launch(struct vcpu *v)
     __vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
 
     v->arch.schedule_tail = arch_vmx_do_resume;
+    /* init guest tsc to start from 0 */
+    rdtscll(host_tsc);
+    v->arch.arch_vmx.tsc_offset = 0 - host_tsc;
+    set_tsc_shift (v, &v->domain->arch.vmx_platform.vmx_pit);
 }
 
 /*
@@ -366,7 +371,6 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
     error |= __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0);
 
     /* TSC */
-    error |= __vmwrite(TSC_OFFSET, 0);
     error |= __vmwrite(CR3_TARGET_COUNT, 0);
 
     /* Guest Selectors */
index e5fb1bc36888e7ae88b10a90155623595e26d87b..e4e6d2b88c5bbd772608d413083054266396545a 100644 (file)
@@ -27,7 +27,6 @@ struct vmx_virpit {
     unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
     u32 period;                /* pit frequency in ns */
     int first_injected;                 /* flag to prevent shadow window */
-    int ticking;    /* indicating it is ticking */
 
     /* virtual PIT state for handle related I/O */
     int read_state;
@@ -51,5 +50,6 @@ static __inline__ s_time_t get_pit_scheduled(
     else
         return -1;
 }
+extern void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit);
 
 #endif /* _VMX_VIRPIT_H_ */